package hexui.components;

import hexgame.GameState;
import hexgame.HexMove;
import hexgame.HexPlayer;

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;

import javax.imageio.ImageIO;
import javax.swing.*;

public class BoardUI extends JPanel implements MouseListener {
	private static final long serialVersionUID = 1L;

	GameState gameState;
	Field[][] fields;
	HashMap<Field, BufferedImage> tiles = new HashMap<Field, BufferedImage>();
	Location selection = null;

	public BoardUI(GameState gameState) {
		this.gameState = gameState;
		this.initFilds();
		this.loadImages();
		this.setSize(fields.length * 74, fields.length * 43);
		this.addMouseListener(this);
	}

	private void initFilds() {

		this.fields = new Field[gameState.getBoardSize() + 2][gameState.getBoardSize() + 2];

		int maxBoardTile = gameState.getBoardSize() + 1;

		for (int x = 0; x < fields.length; x++) {

			for (int y = 0; y < fields.length; y++) {

				if(x == 0 && y > 0 && y < maxBoardTile) {
					fields[x][y] = Field.RED_BORDER;
				}
				else if(x == maxBoardTile && y > 0 && y < maxBoardTile) {
					fields[x][y] = Field.RED_BORDER;
				}
				else if(y == 0 && x > 0 && x <= maxBoardTile) {
					fields[x][y] = Field.BLUE_BORDER;
				}
				else if(y == maxBoardTile && x >= 0 && x < maxBoardTile) {
					fields[x][y] = Field.BLUE_BORDER;
				}

				// We draw empty tiles on all except top left and bottom right.
				else if(x != 0 && x != maxBoardTile) {
					fields[x][y] = Field.EMPTY;
				}
			}
		}
	}

	@Override
	protected void paintComponent(Graphics g) {

		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;

		int draw_x = 0;
		int draw_y = 0;

		for (int x = 0; x < fields.length; x++) {

			for (int y = 0; y < fields.length; y++) {

				draw_y = (y * 43);
				draw_x = x * 49 + (y * 25);

				g2d.drawImage(tiles.get(fields[x][y]), draw_x, draw_y, null);
			}
		}
	}

	private void loadImages() {
		try {
			tiles.put(Field.EMPTY, ImageIO.read(new File("images/hexagon.png")));
			tiles.put(Field.BLUE_SELECTION, ImageIO.read(new File("images/BlueSelection.png")));
			tiles.put(Field.BLUE_BORDER, ImageIO.read(new File("images/BlueBorder.png")));
			tiles.put(Field.RED_SELECTION, ImageIO.read(new File("images/RedSelection.png")));
			tiles.put(Field.RED_BORDER, ImageIO.read(new File("images/RedBorder.png")));
			tiles.put(Field.SELECTION, ImageIO.read(new File("images/Selected.png")));
		}
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private Location calculateLocation(int xCoord, int yCoord) {

		int x, y;

		yCoord = yCoord - 43;
		xCoord = xCoord - 49;

		y = yCoord / 43;
		xCoord = xCoord - (y + 1) * 25;
		x = xCoord / 49;

		x++;
		y++;

		if(x > gameState.getBoardSize() || y > gameState.getBoardSize()) {
			return null;
		}
		
		Location location = new Location(x, y);

		return location;
	}

	public void showMove(HexMove move) {
		// Must add 1 to the positions, to account for the border
		if(move.getPlayer() == HexPlayer.RED_LOCAL) {
			fields[move.getX() + 1][move.getY() + 1] = Field.RED_SELECTION;
		}
		else {
			fields[move.getX() + 1][move.getY() + 1] = Field.BLUE_SELECTION;
		}
		this.repaint();
	}

	public Location getSelection() {
		if((selection != null) && (selection.x > 0) && (selection.x < fields.length - 1) && (selection.y > 0) && (selection.y < fields.length - 1)) {
			fields[selection.x][selection.y] = Field.RED_SELECTION;
			repaint();
			Location selected = selection;
			selection = null;
			return selected;
		}
		else {
			return null;
		}
	}

	@Override
	public void mouseClicked(MouseEvent e) {
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if(gameState.isLocalPlayerTurn() == true) {

			Location newLoc = calculateLocation(e.getX(), e.getY());

			if(newLoc == null) {
				return;
			}
			
			// If this field isn't EMPTY, we shouldn't click it
			if(fields[newLoc.x][newLoc.y] != Field.EMPTY) {
				return;
			}

			// If we have made a selection before
			if(selection != null) {
				// Set the previously selected field back again (if it's still
				// just a selection)
				if(fields[selection.x][selection.y] == Field.SELECTION) {
					fields[selection.x][selection.y] = Field.EMPTY;
				}
			}

			fields[newLoc.x][newLoc.y] = Field.SELECTION;
			selection = newLoc;
			repaint();
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
	}

	@Override
	public void mouseEntered(MouseEvent e) {
	}

	@Override
	public void mouseExited(MouseEvent e) {
	}

}